package com.wk.data4glib.tool;

/**
 * 功能描述： 用来处理 bit 和byte 、int等数值转换的工具类 。  <br>
 *
 * @author 创建人：Aivin     <br>
 *         创建日期： 2017/12/19      <br>
 *         最后修改日期 ：   <br>
 */

public class WkByteBitTools {


    /**
     * 校验飞机的合法性。
     * 收到数据后需要重新计算校验值 然后跟自带的校验
     */
    public static boolean checkTheDataWithverifyValue(byte[] bytes)
    {
        byte reslut = getVerifyValueOfAllBytes_1(bytes) ;
        byte reslut2 = bytes[bytes.length-1] ;
        return  reslut==reslut2 ? true : false ;
    }


    /**
     * 获取整个byte[]  -1 的校验位
     * @param lastBytes byte []
     * @return byte
     */
    private static  byte  getVerifyValueOfAllBytes_1(byte [] lastBytes)
    {
        byte checksum =  0;

        for (int i = 0; i <= lastBytes.length-2; i++) {
            checksum += lastBytes[i];
        }

        checksum = (byte) (checksum % 256) ;
        return  checksum ;
    }

    /**
     * 获得校验位。
     * 计算规则：
     * SUM等于从该数据帧第一字节开始，也就是帧头开始，至该帧数据的最后一字节所有字节的和，
     * 只保留低八位，高位舍去。
     *   P1=s/256; //整除高8位s
     P0=s%256; //取余是低八
     */
    public static  byte[] getVerifyValue(byte [] lastBytes)
    {
        byte checksum =  0;

        for (int i = 0; i <= lastBytes.length-2; i++) {
            checksum += lastBytes[i];
        }

        checksum = (byte) (checksum % 256) ;
        lastBytes[lastBytes.length-1] = checksum;
        return  lastBytes ;
    }



    /**
     * 获得指定数据的校验和
     * 计算规则：
     * SUM等于从该数据帧第一字节开始，也就是帧头开始，至该帧数据的最后一字节所有字节的和，
     * 只保留低八位，高位舍去。
     *   P1=s/256; //整除高8位s
     P0=s%256; //取余是低八
     */
    public static byte  getCheckSum(byte [] data) {
        byte checksum =  0;

        for(byte temp: data){
            checksum+= temp ;
        }

        checksum = (byte) (checksum % 256) ;
        return  checksum ;
    }


    /**
     * 获得校验位。
     * 计算规则：
     * SUM等于从该数据帧第一字节开始，也就是帧头开始，至该帧数据的最后一字节所有字节的和，
     * 只保留低八位，高位舍去。
     *   P1=s/256; //整除高8位s
     P0=s%256; //取余是低八
     */
    public static  byte[] getVerifyValue1(byte [] lastBytes)
    {
        byte checksum =  0;

        for (int i = 0; i <= lastBytes.length-2; i++) {
            checksum += lastBytes[i];
        }

        checksum = (byte) (checksum % 256) ;
        lastBytes[lastBytes.length-1] = checksum;
        return  lastBytes ;
    }


    /**
     * 数组动态扩充容量 <br>
     * 代码并没有真正增加原数组a的容量，只是将a内容复制到新的大数组，<br>
     * 然后让a重新引用大数组。由于Java数组存贮在堆中，原a数组无需释放，会被自动回收。<br>
     */
    public static String [] getNewArrayWithMoreSpaceString( String [] oldArray , String [] increceData  )
    {
        //新数组
        String [] lastArray=new String[oldArray.length+increceData.length];
        //将a数组内容复制新数组b
        System.arraycopy(oldArray, 0, lastArray, 0, oldArray.length);

        for(int i=0 ;i<increceData.length ;i++)
        {
            lastArray[ oldArray.length + i] = increceData[i] ;
        }
        //改变引用
        oldArray=lastArray;
        return   oldArray ;
    }



    /***
     * 指定数组中复制内容到新的数组
     *   arraycopy(Object src,byte srcPos,Object dest, byte destPos,byte length);
     src:源数组
     srcPos:源数组要复制的起始位置
     dest:目的数组
     destPos:目的数组放置的起始位置
     length:要复制的长度
     */
    public static void  copyDataToNewByteteArray(byte[] src, int srcPos , byte[] dest, int destPos , int length)
    {
        System.arraycopy(src, srcPos , dest, destPos, length);
    }


    public static int [] getNewArrayWithMoreSpaceInt( int [] oldArray , int [] increceData  )
    {
        //新数组
        int[] lastArray=new int[oldArray.length+increceData.length];
        //将a数组内容复制新数组b
        System.arraycopy(oldArray, 0, lastArray, 0, oldArray.length);

        for(int i=0 ;i<increceData.length ;i++)
        {
            lastArray[ oldArray.length + i] = increceData[i] ;
        }
        //改变引用
        oldArray=lastArray;
        return   oldArray ;
    }


    /**
     * 数组截取
     *
     * @param srcByte 源数组
     * @param begin   源数组要复制的起始位置
     * @param count   要复制的长度
     * @return
     */
    public static byte[] subBytes(byte[] srcByte, int begin, int count)
    {
        byte[] result = new byte[count];
        System.arraycopy(srcByte, begin, result, 0, count);
        return result;
    }


    /**
     * 将byte转换为一个长度为8的byte数组，数组每个值代表bit
     */
    public static byte[] get8bitsOfOneByteTest(byte mByte){
        byte[] array = new byte[8];
        byte h01= (byte)0x01;

        for (int i = 7; i >= 0; i--)
        {
            //与1与运算- >  0000 0001
            array[i] = (byte)(mByte & h01);
            mByte = (byte) (mByte >> 1);
        }
        return array;
    }

    /**
     * 将byte转换为一个长度为8的byte数组，数组每个值代表bit
     */
    public static byte[] get8bitsOfOneByte(byte b)
    {
        byte[] array = new byte[8];
        for (int i = 7; i >= 0; i--) {
            array[i] = (byte)(b & 1);
            b = (byte) (b >> 1);
        }
        return array;
    }

    /**
     * 获取byte的高四位
     */
    public byte gethe4BitOfByte(byte mByte)
    {
        //0xF0换成二进制 -> 1111 0000（0xF0相当于高四位保留，低四位置为0）
        return (byte)((mByte & 0xF0) >> 4);
    }

    /**
     * 获取byte的低四位
     */
    public byte getLow4BitOfByte(byte mByte)
    {
        //0x0F换成二进制 -> 0000 1111  （0xF0相当于低四位保留，高四位置为0）
        return (byte) (mByte & 0x0F);
    }

    /**
     * bytes转换成十六进制字符串
     * @param b byte数组
     * @return String 每个Byte值之间空格分隔
     */
    public static String byte2HexStr(byte[] b)
    {
        String stmp ;
        StringBuilder sb = new StringBuilder("");
        for (int n = 0; n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0xFF);
            sb.append((stmp.length() == 1) ? "0" + stmp : stmp);
            sb.append(" ");
        }
        return sb.toString().toUpperCase().trim();
    }


    public static String byte2HexStrLikeIos(byte[] b)
    {
        String stmp = "";
        StringBuilder sb = new StringBuilder("");

        int i= 0;
        for (int n = 0; n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0xFF);

            sb.append((stmp.length() == 1) ? "0" + stmp : stmp);
            if(n%2!=0)
            {
                sb.append(" ");
                i++ ;

                if(i%8==0)
                {
                    sb.append("\r\n");
                }
            }


        }
        return sb.toString().toLowerCase().trim();
    }


    public static String byteOne2HexStr(byte  b)
    {
        String  stmp = Integer.toHexString( b & 0xFF);
        return  (stmp.length() == 1) ? "0" + stmp : stmp ;
    }


    public static String byte1ToHexStr(byte mByte)
    {
        String stmp   = Integer.toHexString(mByte & 0xFF);
        return stmp.toUpperCase().trim();
    }


    /***
     * int 类型 转为 1个字节长度的 byte
     */
    public static byte intTo1ByteHex(int intVaue )
    {
        return new Integer(intVaue & 0xff).byteValue();
    }

    /***
     * int 类型 转为 1个字节长度的 byte数组、
     * ？？
     */
    public static byte[] intTo1ByteHexArray(int intVaue )
    {
        byte[] array = new byte[1] ;
        array[0] = new  Integer(intVaue & 0xff).byteValue();
        return array ;

    }



    /***
     * int 类型 转为 4个字节长度的 byte数组。
     * 大端小端翻转 。
     * 邹聪提供。
     * @param intVaue  int
     * @param byteVauesHex byte[]
     */
    public static void intTo4ByteArrayHex(int intVaue, byte[] byteVauesHex)
    {
        for (int i = 0; i < byteVauesHex.length; i++) {
            byteVauesHex[i] = new Integer(intVaue & 0xff).byteValue();
            intVaue = intVaue >> 8;
        }
    }



    /**
     * 将一个byte转为一个 byte数组
     * @param mByte byte
     * @return  byte []
     */
    public static byte []  byte1ToByteArray( byte mByte)
    {
        byte [] bytes= {mByte} ;
        return  bytes;
    }


    /***
     * int 类型 转为 4个字节长度的 byte数组。
     * 正常顺序 。不考虑大端小端翻转 。
     * 邹聪提供。
     * @param intVaue  int
     * @param byteVauesHex byte[]
     */
    public static void intTo4ByteArrayHexNormal(int intVaue, byte[] byteVauesHex)
    {
        for (int i = byteVauesHex.length - 1; i >= 0; i--) {
            byteVauesHex[i] = new Integer(intVaue & 0xff).byteValue();
            intVaue = intVaue >> 8;
        }

    }


    /**
     * 将一个short转为2个字节的数组
     * 算法来源 网络
     * http://blog.csdn.net/thanklife/article/details/17002641
     * 如: pitch = 1900 = 0x076c => 发送顺序：先发0x07，再发0x6c
     * 高位在前，低位在后
     */
    public static byte[] shortTobytes2HeightLow(short number)
    {
        int temp = number;
        byte[] b = new byte[2];
        for (int i = b.length - 1; i >= 0; i--) {
            b[i] = new Integer(temp & 0xff).byteValue();
            temp = temp >> 8;
        }
        return b;
    }

    public static byte[] shortTobytes2_low_height(short number)
    {
        int temp = number;
        byte[] b = new byte[2];
        for (int i = 0; i < b.length; i++) {

            b[i] = new Integer(temp & 0xff).byteValue();
            temp = temp >> 8;
        }
        return b;
    }


    public static  byte[]  intTo4ByteArrayHex_height_low (int intVaue)
    {
        byte[] byteVauesHex = new byte[4] ;
        for (int i = byteVauesHex.length -1; i >=0  ; i--) {
            byteVauesHex[i] = new Integer(intVaue & 0xff).byteValue();
            intVaue = intVaue >> 8;
        }

        return  byteVauesHex ;
    }



    public static  byte[]  intTo4ByteArrayHex_low_height(int intVaue)
    {
        byte[] byteVauesHex = new byte[4] ;
        for (int i = 0; i < byteVauesHex.length; i++) {
            byteVauesHex[i] = new Integer(intVaue & 0xff).byteValue();
            intVaue = intVaue >> 8;
        }

        return  byteVauesHex ;
    }



    public static  byte[]  floatTo4ByteArrayHex_height_low (float intVaue)
    {
        byte[] byteVauesHex = new byte[4] ;
        int fbit = Float.floatToIntBits(intVaue);
        for (int pos = 3; pos >= 0 ; pos -- ) {
            byteVauesHex[pos] = new Integer(fbit).byteValue();
            fbit = fbit >> 8;
        }
        return  byteVauesHex ;
    }


    /**
     *  注： float转byte[] 跟 int转byte[] 是不一样的。
     * @param intVaue float
     * @return  byte[]
     */
    public static  byte[]  floatTo4ByteArrayHex_low_height(float intVaue)
    {
        byte[] byteVauesHex = new byte[4] ;
        int fbit = Float.floatToIntBits(intVaue);
        for (int pos = 0; pos <  4; pos++) {
            byteVauesHex[pos] = new Integer(fbit).byteValue();
            fbit = fbit >> 8;
        }
        return  byteVauesHex ;
    }



    /***
     * 将2个字节的 16进制数组 转化为 一个short
     * 计算算法来源 邹聪。
     * 高位在前，低位在后  的bytes数组
     */
    public static short bytes2ToShort(byte[] srcBytes)
    {
        short result;
        short v1 = (short) (srcBytes[0] & 0xFF);
        short v2 = (short) (srcBytes[1] & 0xFF);
        result = (short) (v1 * 256 + v2);
        return result;
    }

    /***
     * 将2个字节的 16进制数组 转化为 一个short <br>
     * 计算算法来源 邹聪。<br>
     * 低位在前，高位在后  的bytes数组
     */
    public static int bytes2ToShort_low_hight(byte[] src)
    {
        return ((src[0] & 0xFF)
                | ((src[ 1] & 0xFF) << 8)
        );
    }

    /***
     * 将2个字节的 16进制数组 转化为 一个short
     * 计算算法来源 邹聪。
     * 高位在前，低位在后  的bytes数组
     */
    public static double bytes2ToDouble(byte[] srcBytes)
    {
        double result;
        short v1 = (short) (srcBytes[0] & 0xFF);
        short v2 = (short) (srcBytes[1] & 0xFF);
        result = (double) (v1 * 256 + v2);
        return result;
    }

    /**
     * 两个byte转整形，add zc
     * @param res  byte[]
     * @return  int
     */
    public static int byte2int(byte[] res)
    {
        // 一个byte数据左移24位变成0x??000000，再右移8位变成0x00??0000
        return  (res[0] & 0xff) | ((res[1] << 8) & 0xff00);
    }


    /***
     * int 类型 转为 2个字节长度的 byte数组。
     * 大端小端翻转 。
     * 邹聪提供。
     * @param intVaue  int
     * @param byteVauesHex byte[]
     */
    public static void intTo2ByteArrayHex(int intVaue, byte[] byteVauesHex)
    {
        for (int i = 0; i < byteVauesHex.length; i++) {
            byteVauesHex[i] = new Integer(intVaue & 0xff).byteValue();
            intVaue = intVaue >> 8;
        }
    }


    /***
     * int 类型 转为 2个字节长度的 byte数组。
     * 正常顺序。
     * @param intVaue  int
     */
    public static byte[]  intTo2ByteArrayHexNormal(int intVaue )
    {
        byte[] byteVauesHex = new byte[2] ;
        for (int i = byteVauesHex.length - 1; i >= 0; i--) {
            byteVauesHex[i] = new Integer(intVaue & 0xff).byteValue();
            intVaue = intVaue >> 8;
        }
        return byteVauesHex;
    }



    /**
     * 将4个字节长度的 byte数组转为int。
     * 本方法适用于(低位在后，高位在前)的顺序
     */
    public static int bytes4HeightAndLowToInt(byte[] src, int offset)
    {
        return (((src[offset] & 0xFF) << 24)
                | ((src[offset + 1] & 0xFF) << 16)
                | ((src[offset + 2] & 0xFF) << 8)
                | (src[offset + 3] & 0xFF));
    }


    /**
     * 将4个字节长度的 byte数组转为int。<br>
     * 本方法适用于(低位在前，高位在后)的顺序<br>
     * 320项目中用到
     */
    public static int bytes4LowAndHeightToInt(byte[] src, int offset)
    {

        return ((src[offset] & 0xFF)
                | ((src[offset + 1] & 0xFF) << 8)
                | ((src[offset + 2] & 0xFF) << 16)
                | ((src[offset + 3] & 0xFF) << 24));
    }

    /**
     * 将1个字节长度的 byte数组转为int。
     */
    public static int bytes1ToInt(byte[] src)
    {
        return src[0] & 0xFF;
    }

    /**
     * 将一个字节长度的byte 转为 int
     * @param src byte
     * @return int
     */
    public static int byte1ToInt(byte src)
    {
        return src & 0xFF;
    }


    public  static  String getStrByByte(StringBuilder sb , byte byte0)
    {
        sb.replace(0, sb.length(), "") ;
        sb.append(Integer.toHexString( byte0 & 0xFF).toUpperCase()) ;

        if(sb.length()==1)
        {
            sb.insert(0, "0") ;
        }

        return sb.toString() ;

    }

    public static String convertStringToHex(String str) {
        char[] chars = str.toCharArray();
        StringBuffer hex = new StringBuffer();
        for (int i = 0; i < chars.length; i++) {
            hex.append(Integer.toHexString((int) chars[i]));
        }
        return hex.toString();
    }


    /**
     * 将16进制字符串转换为byte[]
     */
    public static byte[] toBytes(String str) {
        if (str == null || str.trim().equals("")) {
            return new byte[0];
        }

        byte[] bytes = new byte[str.length() / 2];
        for (int i = 0; i < str.length() / 2; i++) {
            String subStr = str.substring(i * 2, i * 2 + 2);
            bytes[i] = (byte) Integer.parseInt(subStr, 16);
        }
        return bytes;
    }

    /**
     * 合并两个数组
     */
    public static byte[] concat(byte[] a, byte[] b) {
        byte[] c = new byte[a.length + b.length];
        System.arraycopy(a, 0, c, 0, a.length);
        System.arraycopy(b, 0, c, a.length, b.length);
        return c;
    }

}
